package com.seeyon.apps.brwh.service;

import com.alibaba.fastjson.JSONObject;
import com.seeyon.apps.brwh.entity.*;
import com.seeyon.apps.brwh.kit.HttpKit;
import com.seeyon.apps.brwh.kit.StrKit;
import com.seeyon.apps.collaboration.po.ColSummary;
import com.seeyon.apps.mplus.util.Base64;
import com.seeyon.cap4.template.util.BeanUtil;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.constants.ApplicationCategoryEnum;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.common.filemanager.Constants;
import com.seeyon.ctp.common.filemanager.manager.FileManager;
import com.seeyon.ctp.common.log.CtpLogFactory;
import com.seeyon.ctp.common.po.filemanager.Attachment;
import com.seeyon.ctp.common.po.filemanager.V3XFile;
import com.seeyon.ctp.services.FileDownloadExporter;
import com.seeyon.ctp.util.UUIDLong;
import org.apache.commons.logging.Log;
import org.springframework.web.multipart.MultipartFile;
import www.seeyon.com.utils.UUIDUtil;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

import static java.lang.System.out;

/**
 * OCR票据识别Service
 */
public class OCRRecognizeService {
    private static final Log log = CtpLogFactory.getLog(OCRRecognizeService.class);

    public static final String USED_VEHICLE_INVOICE = "used_vehicle_invoice";
    public static final String getCacheToken = "ORC_RECOGNIZ_TOKEN";
    private static String orcUrl = "https://aip.baidubce.com/rest/2.0/ocr/v1/multiple_invoice";

    private static FileManager fileManager = (FileManager)AppContext.getBean("fileManager");


    public List<Map<String,Object>> recognize(List<MultipartFile> fileList) throws Exception {

        List<Map<String, Object>> resultMapList = new ArrayList<>();
        if(fileList.isEmpty()){
            throw new Exception("文件不能为空！！！！！");
        }
        //获取ORCToken信息
        String token = StrKit.str(AppContext.getCache(getCacheToken));
        if(token.equals("")){
            throw new Exception("获取百度OCR的TOKEN为null，请检查！！！");
        }
        String url = orcUrl + "?access_token="+token;

        //循环获取附件识别
        for (MultipartFile file : fileList) {
            //获取文件名
            String fileName = file.getOriginalFilename().substring(0,file.getOriginalFilename().lastIndexOf("."));
            //获取文件后缀
            String fileSuffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1);
            if(fileName.equals("")){
                throw new Exception("获取文件异常名称异常！！");
            }
            InputStream in = null;
            String base64 = null;
            try {
                in = file.getInputStream();
                byte[] bytes = file.getBytes();
                in.read(bytes);
                base64 = new String(Base64.encodeBase64(bytes),"UTF-8");
            }catch (Exception e){
                log.info("文件转换流异常：",e);
            }finally {
                if(in != null){
                    in.close();
                }
            }
            //封装请求参数
            HashMap<String, Object> dataMap = new HashMap<>();
            if(fileSuffix.equals("png") || fileSuffix.equals("jpg") || fileSuffix.equals("jpeg") || fileSuffix.equals("bmp")){
                dataMap.put("image",base64);
            }else if(fileSuffix.equals("pdf")){
                dataMap.put("pdf_file",base64);
            }else{
                throw new Exception("上传文件格式错误，仅支持【png/jpg/jpeg/bmp/pdf】格式的文件");
            }
            //封装请求header
            HashMap<String, Object> headerMap = new HashMap<>();
            headerMap.put("Content-Type","application/x-www-form-urlencoded");

            String post = null;
            try {
                post = HttpKit.postUrlencoded(url, headerMap, dataMap);
            } catch (Exception e) {
                log.info("请求OCR识别异常：",e);
            }
            //解析返回数据
            if(post == null){
                throw new Exception("百度OCR识别异常，返回null");
            }
            if(post.contains("error_code")){
                JSONObject jsonObject = JSONObject.parseObject(post);
                throw new Exception("百度OCR识别返回错误："+jsonObject.get("error_msg"));
            }
            //开始解析OCR返回识别数据
            List<Map<String, Object>> maps = analysisBody(post);
            log.info("解析后的OCR识别数据："+JSONObject.toJSONString(maps));
            if(!maps.isEmpty()){
                resultMapList.addAll(maps);
            }
        }
        return resultMapList;
    }


    /**
     * 解析返回数据
     * @return
     */
    private static List<Map<String,Object>> analysisBody(String data){
        List<Map<String,Object>> list = new ArrayList<>();

        Map<String,Object> o1 = JSONObject.parseObject(data, Map.class);
        String value = JSONObject.toJSONString(o1.get("words_result"));
        List<Map<String,Object>> valueAddedTaxInvoiceEntity = JSONObject.parseObject(value, List.class);
        for (Map<String,Object> addedTaxInvoiceEntity : valueAddedTaxInvoiceEntity) {
            Map<String, Object> resultMap = new HashMap<>();
            String type = StrKit.str(addedTaxInvoiceEntity.get("type"));
            if(type.equals("vat_invoice")){
                //增值税发票
                ValueAddedTaxInvoiceEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), ValueAddedTaxInvoiceEntity.class);
                resultMap = BeanUtil.beanToMap(result);
            }else if(type.equals("taxi_receipt")){
                //出租车票
                TaxiReceiptEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), TaxiReceiptEntity.class);
                resultMap = BeanUtil.beanToMap(result);
            }else if(type.equals("train_ticket")){
                //火车票
                RailwayTicketEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), RailwayTicketEntity.class);
                resultMap = BeanUtil.beanToMap(result);
            }else if(type.equals("quota_invoice")){
                //定额发票
                QuotaInvoiceEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), QuotaInvoiceEntity.class);
                resultMap = BeanUtil.beanToMap(result);
            }else if(type.equals("air_ticket")){
                //飞机行程单
                AircraftItineraryEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), AircraftItineraryEntity.class);
                resultMap = BeanUtil.beanToMap(result);
            }else if(type.equals("roll_normal_invoice")){
                //卷票
                RollTicketEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), RollTicketEntity.class);
                resultMap = BeanUtil.beanToMap(result);

            }else if(type.equals("printed_invoice")){
                //机打发票
                TypedInvoiceEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), TypedInvoiceEntity.class);
                resultMap = BeanUtil.beanToMap(result);
            }else if(type.equals("bus_ticket")){
                //汽车票
                BusTicketEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), BusTicketEntity.class);
                resultMap = BeanUtil.beanToMap(result);
            }else if(type.equals("toll_invoice")){
                //过路过桥费发票
                TollsForRoadCrossingsEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), TollsForRoadCrossingsEntity.class);
                resultMap = BeanUtil.beanToMap(result);
            }else if(type.equals("ferry_ticket")){
                //船票
                SteamerTicketEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), SteamerTicketEntity.class);
                resultMap = BeanUtil.beanToMap(result);
            }else if(type.equals("motor_vehicle_invoice")){
                //机动车销售发票
                MotorVehicleSalesInvoiceEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), MotorVehicleSalesInvoiceEntity.class);
                resultMap = BeanUtil.beanToMap(result);
            }else if(type.equals("used_vehicle_invoice")){
                //二手车发票
//                ValueAddedTaxInvoiceEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), ValueAddedTaxInvoiceEntity.class);
//                resultMap = BeanUtil.beanToMap(result);
            }else if(type.equals("taxi_online_ticket")){
                //网约车行程单
                HailingItineraryEntity result = JSONObject.parseObject(JSONObject.toJSONString(addedTaxInvoiceEntity.get("result")), HailingItineraryEntity.class);
                resultMap = BeanUtil.beanToMap(result);
            }else{
                log.info("支持该发票类型识别，发票类型为："+type);
                resultMap = null;
            }
            if(resultMap == null){
                continue;
            }
            list.add(resultMap);
        }
        return list;
    }


    //上传文件
    public List<Attachment> upField(List<MultipartFile> fileList) throws IOException, BusinessException {
        List<Attachment> atts = new ArrayList();
        for (MultipartFile multipartFile : fileList) {
            InputStream inputStream = multipartFile.getInputStream();
            ApplicationCategoryEnum category = ApplicationCategoryEnum.cap4Form;
            Constants.ATTACHMENT_TYPE type = Constants.ATTACHMENT_TYPE.FILE;
            V3XFile upV3XFile = fileManager.save(inputStream, category, multipartFile.getOriginalFilename(), new Date(), false);
            fileManager.save(upV3XFile);
            Attachment att = new Attachment(upV3XFile, category, type);
            att.setIdIfNew();
            att.setSubReference(UUIDUtil.getUUIDLong());
            atts.add(att);
            inputStream.close();
        }
        return atts;
    }


    /**
     * 获取百度Ocr识别字段
     * @return
     */
    public ArrayList<Map<String, Object>> getBaiDuOcrFields() {
        ArrayList<Map<String, Object>> fieldMapList = new ArrayList<>();
        try {
            //获取配置文件地址
            String confgOcrFildPah = "apps_res/cap/customCtrlResources/baiduOcrBtnResources/configOcrField/configOcrField.txt";
            //获取配置文件文件目录
            String filePath = AppContext.getCfgHome().getCanonicalPath();
            filePath = filePath.replace("WEB-INF" + File.separator + "cfgHome", confgOcrFildPah);
            byte[] bytes = Files.readAllBytes(Paths.get(filePath));
            String value = new String(bytes, StandardCharsets.UTF_8);
            if(!value.equals("")){
                JSONObject jsonObject = JSONObject.parseObject(value);
                for (String s : jsonObject.keySet()) {
                    HashMap<String, Object> fieldMap = new HashMap<>();
                    fieldMap.put("name",s);
                    fieldMap.put("key",jsonObject.get(s));
                    fieldMap.put("fieldType","text");
                    fieldMapList.add(fieldMap);
                }
            }
        }catch (Exception e){
            log.info("获取百度Ocr识别票据字段配置异常：",e);
        }
        return fieldMapList;
    }

}
